package wrapper

import (
	"fmt"
	"gitee.com/ymofen/gobase"
	"github.com/suiyunonghen/dxsvalue"
	"io"
	"runtime"
	"strings"
	"sync/atomic"
)

var (
	supervalue_obj_alive_cnt int32
)

func GetSuperValueStatus() string {
	return fmt.Sprintf("objalive-cnt:%d", supervalue_obj_alive_cnt)
}

/*
# column-spliter=,
# head-after=true
id,connstr
*/
func TextReader2SVArray(reader io.Reader, lst *SuperValue) int {

	colSpliter := ","
	headFlag := false
	var headColumns []string
	var strlst []string

	n := 0

	gobase.ReadPerLineEx(reader, func(idx int64, line []byte) bool {
		strLine := gobase.Trim(string(line))
		if len(strLine) == 0 {
			return true
		}
		if strLine[0] == '#' {
			str := gobase.Trim(string(line[1:]))
			s1, s2 := gobase.Split2Str(str, "=")
			if s1 == "column-spliter" {
				colSpliter = gobase.UnEscapeStr4Line(gobase.Trim(s2))
			} else if s1 == "head-after" {
				headFlag = gobase.TryStrToBool(s2, true)
			}
		} else {
			if len(headColumns) == 0 || headFlag {
				strlst = strings.Split(strLine, colSpliter)
			} else {
				strlst = strings.SplitN(strLine, colSpliter, len(headColumns))
			}

			if headFlag {
				headColumns = strlst
				headFlag = false
			} else {
				itm := lst.AppendObject()
				for j := 0; j < len(strlst); j++ {
					itm.SetKeyValue(gobase.CheckGetStrlist(headColumns, j, fmt.Sprintf("%d", j)), gobase.Trim(strlst[j]))
				}
				n++
			}
		}
		return true
	})
	return n
}

/*
id,name\n
01,张三\n
02,XXX\n
*/
func TextData2SVArray(str string, lst *SuperValue, lst_sep, val_sep string, firstkeyflag bool) int {
	strlst := strings.Split(str, lst_sep)
	var fields []string
	n := 0
	for i := 0; i < len(strlst); i++ {
		vals := strings.Split(strlst[i], val_sep)
		if i == 0 && firstkeyflag {
			fields = vals
		} else {
			itm := lst.AppendObject()
			for j := 0; j < len(vals); j++ {
				itm.SetKeyValue(gobase.CheckGetStrlist(fields, j, fmt.Sprintf("%d", j)), gobase.Trim(vals[j]))
			}
			n++
		}
	}
	return n
}

func NewValueFromJson(buf []byte, useCache bool, sharebinary bool) (*SuperValue, error) {
	val, err := dxsvalue.NewValueFromJson(buf, useCache, sharebinary)
	if err != nil {
		return nil, err
	}
	if val == nil {
		return nil, fmt.Errorf("JSON解析异常, 数据:%s", string(buf))
	}
	return NewSVFromVal(val), nil
}

func SVClear(sv *SuperValue) {
	if sv != nil {
		sv.Clear()
	}
}

func NewSVObjectByKeyValues(kv ...interface{}) *SuperValue {
	rval := &SuperValue{
		val: dxsvalue.NewObject(false),
	}
	rval.SetKeyValues(kv...)
	return rval
}

/*
*
如果没有则Painc
*/
func NewSVObjectFromString(str string) *SuperValue {
	rval, err := NewSVFromBuf([]byte(str))
	if err != nil {
		panic(fmt.Sprintf("解析%s异常:%s", str, err.Error()))
	}
	return rval
}

func NewSVObjectCache(cache bool) *SuperValue {
	rval := &SuperValue{
		useCache: cache,
		val:      dxsvalue.NewObject(cache),
	}
	atomic.AddInt32(&supervalue_obj_alive_cnt, 1)
	runtime.SetFinalizer(rval, func(obj interface{}) {
		atomic.AddInt32(&supervalue_obj_alive_cnt, -1)
	})
	return rval
}

func NewSVObject() *SuperValue {
	return NewSVObjectCache(false)
}

func NewSVArray() *SuperValue {
	return NewSVArrayCache(false)
}

func NewSVArrayCache(cache bool) *SuperValue {
	rval := &SuperValue{
		useCache: cache,
		val:      dxsvalue.NewArray(cache),
	}
	atomic.AddInt32(&supervalue_obj_alive_cnt, 1)
	runtime.SetFinalizer(rval, func(obj interface{}) {
		atomic.AddInt32(&supervalue_obj_alive_cnt, -1)
	})
	return rval
}

func NewSVFromVal(val *dxsvalue.DxValue) *SuperValue {
	rval := &SuperValue{
		val: val,
	}
	atomic.AddInt32(&supervalue_obj_alive_cnt, 1)
	runtime.SetFinalizer(rval, func(obj interface{}) {
		atomic.AddInt32(&supervalue_obj_alive_cnt, -1)
	})
	return rval
}

func NewSVObjectFromBufIfErrThenNew(buf []byte) *SuperValue {
	if len(buf) < 2 {
		return NewSVObject()
	}

	val, _ := dxsvalue.NewValueFromJson(buf, false, false)

	if val == nil {
		return NewSVObject()
	}
	return NewSVFromVal(val)
}

func NewSVObjectFromBufIfErrThenNewCache(buf []byte, cache bool) *SuperValue {
	val, _ := dxsvalue.NewValueFromJson(buf, cache, false)

	if val == nil {
		return NewSVObjectCache(cache)
	}
	return NewSVFromVal(val)
}

func NewSVFromBufEx(buf []byte, def *SuperValue) *SuperValue {
	val, err := dxsvalue.NewValueFromJson(buf, false, false)
	if err != nil {
		return def
	}
	if val == nil {
		return def
	}
	return NewSVFromVal(val)
}

func NewSVFromBufCache(buf []byte, useCache bool) (*SuperValue, error) {
	val, err := dxsvalue.NewValueFromJson(buf, useCache, false)
	if err != nil {
		return nil, err
	}
	if val == nil {
		return nil, fmt.Errorf("JSON解析异常, 数据:%s", string(buf))
	}
	return NewSVFromVal(val), nil
}

func NewSVFromBuf(buf []byte) (*SuperValue, error) {
	return NewSVFromBufCache(buf, false)
}

func NewSVFrom(val interface{}, useCache bool) (*SuperValue, error) {
	if v, ok := val.([]byte); ok {
		return NewSVFromBufCache(v, useCache)
	}

	if v, ok := val.(string); ok {
		return NewSVFromBufCache([]byte(v), useCache)
	}

	if v, ok := val.(*SuperValue); ok {
		if useCache {
			return v.CloneCache(true), nil
		}
		return v, nil
	}

	if v, ok := val.(*dxsvalue.DxValue); ok {
		if useCache {
			return NewSVFromVal(v.Clone(true)), nil
		}
		return NewSVFromVal(v), nil
	}

	return nil, fmt.Errorf("未知的数据:%+v", val)
}

func NewSVFromFileCache(filename string, cache bool) (*SuperValue, error) {
	buf, err := gobase.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	return NewSVFromBufCache(buf, cache)
}

func NewSVFromFile(filename string) (*SuperValue, error) {
	buf, err := gobase.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	return NewSVFromBuf(buf)
}
